use std::ptr;

use codec::{encode_u16, encode_u8};

pub mod codec;
pub mod types;

pub const HEAD: u16 = 0xE11E;
pub const HEAD0: u8 = 0xE1;
pub const HEAD1: u8 = 0x1E;

pub const MIN_LEN: usize = 6;

#[inline(always)]
pub fn memcpy(dest: &mut [u8], src: &[u8]) {
    unsafe {
        ptr::copy_nonoverlapping(
            src.as_ptr(), 
            dest.as_mut_ptr(), 
            src.len()
        );
    }
}

pub fn new_buf(len: usize) -> Box<[u8]> {
    let mut buf = Vec::with_capacity(len);
    unsafe {
        buf.set_len(len);
    }
    buf.into_boxed_slice()
}

#[inline(always)]
pub fn new_min_frame(ts: u8, seq: u8) -> [u8; MIN_LEN] {
    [HEAD0, HEAD1, 0, MIN_LEN as u8, ts, seq]
}

pub fn new_frame(ts: u8, seq: u8, cmd: u16, body: &[u8]) -> Box<[u8]> {
    let len = MIN_LEN + 2 + body.len();
    let mut buf = new_buf(len);
    encode_u16(&mut buf, HEAD);
    encode_u16(&mut buf[2..], len as u16);
    encode_u8(&mut buf[4..], ts);
    encode_u8(&mut buf[5..], seq);
    encode_u16(&mut buf[6..], cmd);
    memcpy(&mut buf[8..], body);
    buf
}

pub fn new_res_frame(ts: u8, seq: u8, cmd: u16, state: u8, body: &[u8]) -> Box<[u8]> {
    let len = MIN_LEN + 2 + 1 + body.len();
    let mut buf = new_buf(len);
    encode_u16(&mut buf, HEAD);
    encode_u16(&mut buf[2..], len as u16);
    encode_u8(&mut buf[4..], ts);
    encode_u8(&mut buf[5..], seq);
    encode_u16(&mut buf[6..], cmd);
    encode_u8(&mut buf[8..], state);
    memcpy(&mut buf[9..], body);
    buf
}


